#include "display7seg_drv.h"

#if (DISP7SEG_C_USE_DEMUX == pdON)
static uint offset = 0; 	// Deslogamento do primeira linha de endereço do demux.
static uint qtdCMux = 0; 	// Quantidade de endereços contêm o demux
#endif

// -------------------------------------------------------------------------------------------------------------------
// Descrição: 	Inicializa a porta do processador para controlar os módulos de 7 segmentos
// Parametro:	Nenhum
// Retorna:		Nada
// -------------------------------------------------------------------------------------------------------------------
void disp7seg_SetupPorts(void) {
	uint x;

	#if (DISP7SEG_C_USE_DEMUX == pdON)
	// Quantide de deslocamento do primeiro bit do controle de acionamento de módulo
	//	Ex: Se for BIT_22 offset 22
	offset = 0;
	for (x=0;x<32;x++) { if (_BV(x)&DISP7SEG_C_INIT) { offset = x; break; }}

	// Calcula a mascara das linhas de endereços do demux de acordo com a quantidade de displays
	//	Ex: Se for 3 linhas o mask = 0b111
	uint mask = 0;
	for (x=0;x<DISP7SEG_N_MODULE;x++) mask |= x;

	// Quantidade de linhas de endereços do demux
	//	Ex: Se for 3 linhas o qtdCMux = 3
	qtdCMux = 0;
	for (x=0;x<32;x++) if (mask&_BV(x)) qtdCMux++;
	#endif

	// Pinos para os leds 1 a 8 como saida
	DISP7SEG_DIR |= (
		DISP7SEG_LED1 |
		DISP7SEG_LED2 |
		DISP7SEG_LED3 |
		DISP7SEG_LED4 |
		DISP7SEG_LED5 |
		DISP7SEG_LED6 |
		DISP7SEG_LED7 |
		DISP7SEG_LED8
	);

	// desligar os leds dos segmentos
	DISP7SEG_SET = (
		DISP7SEG_LED1 |
		DISP7SEG_LED2 |
		DISP7SEG_LED3 |
		DISP7SEG_LED4 |
		DISP7SEG_LED5 |
		DISP7SEG_LED6 |
		DISP7SEG_LED7 |
		DISP7SEG_LED8
	);

	// Pinos para os comuns dos leds como saida
	// desligar os comuns dos leds
	u32 bit = DISP7SEG_C_INIT;
	for (x=0;x<DISP7SEG_N_MODULE;x++) {
		DISP7SEG_C_DIR |= bit; // Pinos para os comuns dos leds como saida
		DISP7SEG_C_CLR = bit;	// desligar os comuns dos leds
		bit = bit<<1;
	}
}

void disp7seg_WriteSeg(int value) {
	#if (DISP7SEG_COMMON == DISP7SEG_COMMON_ANODE)
	if (value & 0x80)	DISP7SEG_CLR = DISP7SEG_LED1; else DISP7SEG_SET = DISP7SEG_LED1;
	if (value & 0x40)	DISP7SEG_CLR = DISP7SEG_LED2; else DISP7SEG_SET = DISP7SEG_LED2;
	if (value & 0x20)	DISP7SEG_CLR = DISP7SEG_LED3; else DISP7SEG_SET = DISP7SEG_LED3;
	if (value & 0x10)	DISP7SEG_CLR = DISP7SEG_LED4; else DISP7SEG_SET = DISP7SEG_LED4;
	if (value & 0x8)	DISP7SEG_CLR = DISP7SEG_LED5; else DISP7SEG_SET = DISP7SEG_LED5;
	if (value & 0x4)	DISP7SEG_CLR = DISP7SEG_LED6; else DISP7SEG_SET = DISP7SEG_LED6;
	if (value & 0x2)	DISP7SEG_CLR = DISP7SEG_LED7; else DISP7SEG_SET = DISP7SEG_LED7;
	if (value & 0x1)	DISP7SEG_CLR = DISP7SEG_LED8; else DISP7SEG_SET = DISP7SEG_LED8;
	#else
	if (value & 0x80)	DISP7SEG_SET = DISP7SEG_LED1; else DISP7SEG_CLR = DISP7SEG_LED1;
	if (value & 0x40)	DISP7SEG_SET = DISP7SEG_LED2; else DISP7SEG_CLR = DISP7SEG_LED2;
	if (value & 0x20)	DISP7SEG_SET = DISP7SEG_LED3; else DISP7SEG_CLR = DISP7SEG_LED3;
	if (value & 0x10)	DISP7SEG_SET = DISP7SEG_LED4; else DISP7SEG_CLR = DISP7SEG_LED4;
	if (value & 0x8)	DISP7SEG_SET = DISP7SEG_LED5; else DISP7SEG_CLR = DISP7SEG_LED5;
	if (value & 0x4)	DISP7SEG_SET = DISP7SEG_LED6; else DISP7SEG_CLR = DISP7SEG_LED6;
	if (value & 0x2)	DISP7SEG_SET = DISP7SEG_LED7; else DISP7SEG_CLR = DISP7SEG_LED7;
	if (value & 0x1)	DISP7SEG_SET = DISP7SEG_LED8; else DISP7SEG_CLR = DISP7SEG_LED8;
	#endif
}

// -------------------------------------------------------------------------------------------------------------------
// Descrição: 	Liga somente o módulo desejado desligando os demais
// Parametro:	module: Módulo que deseja acionar, valores de 0 a DISP7SEG_N_MODULE-1, valor -1 deslisga todos
// Retorna:		Nada
// -------------------------------------------------------------------------------------------------------------------
void disp7seg_SetModule(int module) {
	// se usar um demux na linha de seleção
	#if (DISP7SEG_C_USE_DEMUX == pdON)
	u32 bit = offset; // pega o primeiro bit de endereço do demux
	// Fazer para todos os bits do module
	uint x; for (x=0;x<qtdCMux;x++) {
		// Cada bit do module corresponde a cada bit do endereço do demux.
		// Se o bit do module estiver acionado vamos ligar o pino do endereço, senão manter desligado
		if (module&_BV(x)) DISP7SEG_C_SET = _BV(bit); else DISP7SEG_C_CLR = _BV(bit);
		bit++; // ir para o próximo bit
	}
	#else
	int x;
	u32 bit = DISP7SEG_C_INIT;
	for (x=0;x<DISP7SEG_N_MODULE;x++) {
		#if (DISP7SEG_COMMON == DISP7SEG_COMMON_ANODE)
		if (x==module) DISP7SEG_C_CLR = bit; else  DISP7SEG_C_SET = bit;
		#else
		if (x==module) DISP7SEG_C_SET = bit; else  DISP7SEG_C_CLR = bit;
		#endif
		bit = bit<<1;
	}
	#endif
}

